﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Globalization;

namespace AnonsaiWPF.CSharp
{
    /// <summary>
    /// Interaction logic for Validation.xaml
    /// </summary>
    public partial class ValidationDemo : Window, IWindow
    {
        public Grid Root
        {
            get
            {
                return this.RootVisual;
            }
        }

        public void SetTheme()
        {
        }
  
        public ValidationDemo()
        {
            InitializeComponent();

            this.NumberEditor.Minimum = Int64.Parse(this.Minimum.Text);
            this.NumberEditor.Maximum = Int64.Parse(this.Maximum.Text);

            this.FixedPointEditor.Minimum = Int64.Parse(this.Minimum.Text);
            this.FixedPointEditor.Maximum = Int64.Parse(this.Maximum.Text);

            this.CurrencyEditor.Minimum = Int64.Parse(this.Minimum.Text);
            this.CurrencyEditor.Maximum = Int64.Parse(this.Maximum.Text);

            this.NumberEditor.Value = 0;          
         
            this.Minimum.TextChanged += new TextChangedEventHandler(Minimum_TextChanged);
            this.Maximum.TextChanged += new TextChangedEventHandler(Maximum_TextChanged);

            ValueValidation validation = new ValueValidation(this.NumberEditor.Minimum, this.NumberEditor.Maximum);
            this.LayoutRoot.DataContext = validation;
        }

        public void DetachContent()
        {
            RemoveLogicalChild(Content);
        }

        void Maximum_TextChanged(object sender, TextChangedEventArgs e)
        {
            long result;
            if (Int64.TryParse(this.Maximum.Text, out result))
            {
                this.NumberEditor.Maximum = result;
                this.CurrencyEditor.Maximum = result;
                this.FixedPointEditor.Maximum = result;
            }
            else
            {
                this.Maximum.Text = "10000";
            }

            ValueValidation validation = new ValueValidation(this.NumberEditor.Minimum, this.NumberEditor.Maximum);
            this.LayoutRoot.DataContext = validation;    
       
        }

        void Minimum_TextChanged(object sender, TextChangedEventArgs e)
        {
            long result;
            if (Int64.TryParse(this.Minimum.Text, out result))
            {
                this.NumberEditor.Minimum = result;
                this.CurrencyEditor.Minimum = result;
                this.FixedPointEditor.Minimum = result;
            }
            else
            {
                this.Minimum.Text = "-10000";
            }

            ValueValidation validation = new ValueValidation(this.NumberEditor.Minimum, this.NumberEditor.Maximum);
            this.LayoutRoot.DataContext = validation;    
       
        }
    }

    public class ValueValidation : INotifyPropertyChanged
    {
        private string textValue = "0.00";
        private string textValueCurrency = "0.00";
        private string textValueFixedPoint = "0.00";

        private decimal minimum;
        private decimal maximum;

        public ValueValidation(decimal minimum, decimal maximum)
        {
            this.minimum = minimum;
            this.maximum = maximum;
        }

        /// <summary>
        /// Gets or sets the text value.
        /// </summary>
        /// <value>The text value.</value>
        public string TextValue
        {
            get
            {
                return this.textValue;
            }
            set
            {
                decimal parsed;
                if (decimal.TryParse(value, out parsed))
                {

                    if (parsed < this.minimum)
                    {
                        throw new ArgumentException("Value is less than the Minimum value!");
                    }
                    else if (parsed > this.maximum)
                    {
                        throw new ArgumentException("Value is greater than the Maximum value!");
                    }

                    this.textValue = value;
                    this.OnPropertyChanged("TextValue");
                }
            }
        }

        /// <summary>
        /// Gets or sets the text value fixed point.
        /// </summary>
        /// <value>The text value fixed point.</value>
        public string TextValueFixedPoint
        {
            get
            {
                return this.textValueFixedPoint;
            }
            set
            {
                decimal parsed;
                if (decimal.TryParse(value, out parsed))
                {
                    if (parsed < this.minimum)
                    {
                        throw new ArgumentException("Value is less than the Minimum value!");
                    }
                    else if (parsed > this.maximum)
                    {
                        throw new ArgumentException("Value is greater than the Maximum value!");
                    }

                    this.textValueFixedPoint = value;
                    this.OnPropertyChanged("TextValueFixedPoint");
                }
            }
        }

        private static void BuildValueFromText(string str, string separator, StringBuilder builder, bool hasSeparator)
        {
            for (int i = 0; i < str.Length; i++)
            {
                BuildCorrectCharacter(str, separator, builder, i, hasSeparator);
            }
        }

        /// <summary>
        /// Gets the value string.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="separator">The separator.</param>
        /// <param name="hasSeparator">if set to <c>true</c> [has separator].</param>
        /// <returns></returns>
        public static string GetValueString(string text, string separator, bool hasSeparator)
        {
            string res = "";
            string pointSeparator = separator;

            StringBuilder builder = new StringBuilder();

            BuildValueFromText(text, pointSeparator, builder, hasSeparator);

            res = builder.ToString();

            return res;
        }

        private static void BuildCorrectCharacter(string str, string separator, StringBuilder builder, int i, bool hasSeparator)
        {
            if (Char.IsDigit(str[i]))
            {
                builder.Append(str[i]);
            }
            else
            {
                if (str[i].ToString().Equals(separator) && hasSeparator)
                {
                    builder.Append(".");
                }
            }
        }

        /// <summary>
        /// Gets or sets the currency string.
        /// </summary>
        /// <value>The text value currency.</value>
        public string TextValueCurrency
        {
            get
            {
                return this.textValueCurrency;
            }
            set
            {
                decimal parsed;
                string newValue = GetValueString(value, CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator, true);

                if (decimal.TryParse(newValue, out parsed))
                {

                    if (parsed < this.minimum)
                    {
                        throw new ArgumentException("Value is less than the Minimum value!");
                    }
                    else if (parsed > this.maximum)
                    {
                        throw new ArgumentException("Value is greater than the Maximum value!");
                    }

                    this.textValueCurrency = value;
                    this.OnPropertyChanged("TextValueCurrency");
                }
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion
    }
}
